// ..\MCHdTree\CMCHTreeView.cpp : implementation file
//

#include "stdafx.h"
#include "..\MCHdTree\CMCHTreeView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

/*
if use MFC firmwork, the base class should be CView,
else use CWnd as base class!!!
*/

// CMCHTreeView

IMPLEMENT_DYNCREATE(CMCHTreeView, CMCT_BASE_CLASS)


BEGIN_MESSAGE_MAP(CMCHTreeView, CMCT_BASE_CLASS)
	ON_WM_CREATE()
	ON_WM_HSCROLL()
	ON_WM_SIZE()
	ON_NOTIFY(HDN_ITEMCHANGED, HEADER_ID, OnHdNtf)
	ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
	ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
	ON_COMMAND(ID_EDIT_CUT, OnEditCut)
END_MESSAGE_MAP()


CMCHTreeView::CMCHTreeView() 
				:m_dwCharWidth(8),
				 m_dwCreateStyle(WS_VISIBLE | WS_TABSTOP | WS_CHILD | WS_BORDER | 
								TVS_HASBUTTONS|TVS_HASLINES|TVS_LINESATROOT|
								TVS_EDITLABELS|TVS_NOTOOLTIPS/*|TVS_CHECKBOXES*/|TVS_NOHSCROLL)
{
}

CMCHTreeView::~CMCHTreeView()
{
}
// CMCHTreeView diagnostics

#ifdef _DEBUG
void CMCHTreeView::AssertValid() const
{
	CMCT_BASE_CLASS::AssertValid();
}

void CMCHTreeView::Dump(CDumpContext& dc) const
{
	CMCT_BASE_CLASS::Dump(dc);
}
#endif //_DEBUG

// CMCHTreeView message handlers

int CMCHTreeView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CMCT_BASE_CLASS::OnCreate(lpCreateStruct) == -1)
		return -1;

	// TODO:  Add your specialized creation code here
	m_cMCTree.Create(m_dwCreateStyle, CRect(), this, TREE_ID);
	m_cHeader.Create(WS_CHILD | WS_VISIBLE | HDS_FULLDRAG, CRect(), this, HEADER_ID);
	RECT      rc;
	HDLAYOUT  hdl;
	WINDOWPOS wpos;
	hdl.prc = &rc;
	hdl.pwpos = &wpos;
	m_cHeader.Layout(&hdl);
	m_dwHdcy=wpos.cy;

	return 0;
}

void CMCHTreeView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	// TODO: Add your message handler code here and/or call default

	//
	// Get and set the horizonal scroll bar information
	//
	SCROLLINFO si;
	si.cbSize = sizeof (si) ;
	si.fMask  = SIF_ALL ;
	GetScrollInfo (SB_HORZ, &si) ;
	UINT nOldPos=si.nPos;
	switch (nSBCode)
	{
	case   SB_LINELEFT:
		si.nPos -= m_dwCharWidth ;
		break ;

	case   SB_LINERIGHT:
		si.nPos += m_dwCharWidth ;
		break ;

	case   SB_PAGELEFT:
		si.nPos -= si.nPage ;
		break ;

	case   SB_PAGERIGHT:
		si.nPos += si.nPage ;
		break ;

	case   SB_THUMBPOSITION:
		si.nPos = si.nTrackPos ;
		break ;

	default :
		break ;
	}
	if(si.nPos>(si.nMax-static_cast<int>(si.nPage)))	{si.nPos=si.nMax-si.nPage;}
	if(si.nPos<si.nMin)	{si.nPos=si.nMin;}

	// scroll tree
	m_cMCTree.SetHPos(si.nPos);
	// move header
	m_cHeader.MoveWindow(-si.nPos,0,si.nPage+si.nPos, m_dwHdcy);
	//update hscroll
	SetScrollInfo (SB_HORZ, &si, TRUE);

}

void CMCHTreeView::OnSize(UINT nType, int cx, int cy)
{
	CMCT_BASE_CLASS::OnSize(nType, cx, cy);

	// TODO: Add your message handler code here
	RePosCtrl();
	SetHScroll(cx);
}

void CMCHTreeView::SetHScroll(int cx)
{
	DWORD dwMax, dwPos;
	m_cMCTree.GetHPosInfo(&dwPos, &dwMax);
	if(cx<dwMax)
	{
		SCROLLINFO sif;
		memset(&sif, 0, sizeof(sif));
		sif.cbSize=sizeof(sif);
		sif.fMask=SIF_ALL;
		sif.nMax=dwMax;
		sif.nPage=cx;
		sif.nPos=dwPos;
		m_cMCTree.SetHPos(sif.nPos);
		m_cHeader.MoveWindow(-dwPos, 0, cx+dwPos, m_dwHdcy);
		SetScrollInfo(SB_HORZ, &sif);
		ShowScrollBar(SB_HORZ, TRUE);
	}
	else
	{
		m_cHeader.MoveWindow(0, 0, cx, m_dwHdcy);
		m_cMCTree.SetHPos(0);
		ShowScrollBar(SB_HORZ, FALSE);
	}

}

void CMCHTreeView::OnHdNtf(NMHDR* pNMHDR, LRESULT* pResult)
{
	NMHEADER* pNMHead=reinterpret_cast<NMHEADER*>(pNMHDR);
	m_cMCTree.EditMCTClmnWidth(pNMHead->iItem, pNMHead->pitem->cxy);
	RECT rc;
	GetClientRect(&rc);
	SetHScroll(rc.right);
}

void CMCHTreeView::RePosCtrl(void)
{

	// Reposition the header control so that it is placed at 
	// the top of its parent window's client area.
	RECT rc;
	GetClientRect(&rc);
	m_cMCTree.MoveWindow(0,m_dwHdcy,rc.right,rc.bottom-m_dwHdcy);

	int pos=GetScrollPos(SB_HORZ);
	m_cHeader.MoveWindow(-pos,0,rc.right+pos, m_dwHdcy);

}

//
// column interface
//
BOOL CMCHTreeView::InsertMCTClmn(int nPos, HDITEM* phdi, WORD wSubId, DWORD dwFlag)
{
	if(-1==m_cHeader.InsertItem(nPos, phdi))
	{
		return FALSE;
	}

	if(FALSE==m_cMCTree.InsertMCTClmn(nPos, phdi->cxy, wSubId, dwFlag))
	{
		m_cHeader.DeleteItem(nPos);
	}

	return TRUE;
}

BOOL CMCHTreeView::DeleteMCTClmn(int nPos)
{
	m_cMCTree.DeleteMCTClmn(nPos);
	m_cHeader.DeleteItem(nPos);
	return TRUE;
}


void CMCHTreeView::OnEditPaste()
{
	// TODO: Add your command handler code here
	m_cMCTree.DoPaste();
}

void CMCHTreeView::OnEditCopy()
{
	// TODO: Add your command handler code here
	m_cMCTree.DoCopy();
}

void CMCHTreeView::OnEditCut()
{
	// TODO: Add your command handler code here
	m_cMCTree.DoCut();
}
